package com.example.studentknowledge.service;

import com.example.studentknowledge.entity.PointRecord;
import com.example.studentknowledge.entity.User;
import com.example.studentknowledge.repository.PointRecordRepository;
import com.example.studentknowledge.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 积分服务类
 */
@Service
@Transactional
public class PointService {
    
    @Autowired
    private PointRecordRepository pointRecordRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Value("${app.points.article-create:10}")
    private Integer articleCreatePoints;
    
    @Value("${app.points.article-comment:5}")
    private Integer articleCommentPoints;
    
    @Value("${app.points.article-like:2}")
    private Integer articleLikePoints;
    
    @Value("${app.points.daily-login:1}")
    private Integer dailyLoginPoints;
    
    /**
     * 添加积分
     */
    public void addPoints(User user, Integer points, PointRecord.PointType type, String description) {
        addPoints(user, points, type, description, null);
    }
    
    /**
     * 添加积分（带关联对象ID）
     */
    public void addPoints(User user, Integer points, PointRecord.PointType type, String description, Long referenceId) {
        // 创建积分记录
        PointRecord record = new PointRecord(user, points, type, description, referenceId);
        pointRecordRepository.save(record);
        
        // 更新用户总积分
        user.setPoints(user.getPoints() + points);
        userRepository.save(user);
    }
    
    /**
     * 扣除积分
     */
    public void deductPoints(User user, Integer points, PointRecord.PointType type, String description) {
        deductPoints(user, points, type, description, null);
    }
    
    /**
     * 扣除积分（带关联对象ID）
     */
    public void deductPoints(User user, Integer points, PointRecord.PointType type, String description, Long referenceId) {
        // 检查积分是否足够
        if (user.getPoints() < points) {
            throw new RuntimeException("积分不足");
        }
        
        // 创建积分记录（负数表示扣除）
        PointRecord record = new PointRecord(user, -points, type, description, referenceId);
        pointRecordRepository.save(record);
        
        // 更新用户总积分
        user.setPoints(user.getPoints() - points);
        userRepository.save(user);
    }
    
    /**
     * 发布文章奖励积分
     */
    public void rewardForArticleCreate(User user, Long articleId) {
        addPoints(user, articleCreatePoints, PointRecord.PointType.ARTICLE_CREATE, 
                "发布文章奖励", articleId);
    }
    
    /**
     * 评论文章奖励积分
     */
    public void rewardForComment(User user, Long commentId) {
        addPoints(user, articleCommentPoints, PointRecord.PointType.ARTICLE_COMMENT, 
                "评论文章奖励", commentId);
    }
    
    /**
     * 点赞文章奖励积分
     */
    public void rewardForLike(User user, Long articleId) {
        addPoints(user, articleLikePoints, PointRecord.PointType.ARTICLE_LIKE, 
                "点赞文章奖励", articleId);
    }
    
    /**
     * 每日登录奖励积分
     */
    public void rewardForDailyLogin(User user) {
        // 检查今日是否已有登录记录
        if (!pointRecordRepository.existsTodayLoginRecord(user)) {
            addPoints(user, dailyLoginPoints, PointRecord.PointType.DAILY_LOGIN, "每日登录奖励");
        }
    }
    
    /**
     * 管理员调整积分
     */
    public void adjustPoints(User user, Integer points, String reason) {
        PointRecord.PointType type = points > 0 ? PointRecord.PointType.ADMIN_ADJUST : PointRecord.PointType.ADMIN_ADJUST;
        String description = (points > 0 ? "管理员增加积分: " : "管理员扣除积分: ") + reason;
        
        if (points > 0) {
            addPoints(user, points, type, description);
        } else {
            deductPoints(user, Math.abs(points), type, description);
        }
    }
    
    /**
     * 获取用户积分记录
     */
    public Page<PointRecord> getUserPointRecords(User user, Pageable pageable) {
        return pointRecordRepository.findByUserOrderByCreatedAtDesc(user, pageable);
    }
    
    /**
     * 获取积分记录（按类型）
     */
    public Page<PointRecord> getPointRecordsByType(PointRecord.PointType type, Pageable pageable) {
        return pointRecordRepository.findByTypeOrderByCreatedAtDesc(type, pageable);
    }
    
    /**
     * 获取用户在指定时间范围内的积分记录
     */
    public List<PointRecord> getUserPointRecordsByDateRange(User user, LocalDateTime startDate, LocalDateTime endDate) {
        return pointRecordRepository.findByUserAndCreatedAtBetween(user, startDate, endDate);
    }
    
    /**
     * 计算用户总积分
     */
    public Integer calculateUserTotalPoints(User user) {
        Integer totalPoints = pointRecordRepository.sumPointsByUser(user);
        return totalPoints != null ? totalPoints : 0;
    }
    
    /**
     * 计算用户在指定时间范围内的积分变化
     */
    public Integer calculateUserPointsInDateRange(User user, LocalDateTime startDate, LocalDateTime endDate) {
        Integer points = pointRecordRepository.sumPointsByUserAndDateRange(user, startDate, endDate);
        return points != null ? points : 0;
    }
    
    /**
     * 获取用户积分统计
     */
    public List<Object[]> getUserPointStatistics(User user) {
        return pointRecordRepository.getPointStatisticsByUser(user);
    }
    
    /**
     * 同步用户积分（重新计算并更新）
     */
    public void syncUserPoints(User user) {
        Integer totalPoints = calculateUserTotalPoints(user);
        user.setPoints(totalPoints);
        userRepository.save(user);
    }
    
    /**
     * 获取积分规则说明
     */
    public String getPointRules() {
        return String.format(
            "积分规则说明:\n" +
            "1. 发布文章: +%d 积分\n" +
            "2. 评论文章: +%d 积分\n" +
            "3. 点赞文章: +%d 积分\n" +
            "4. 每日登录: +%d 积分\n" +
            "5. 新用户注册: +10 积分\n" +
            "6. 积分可用于系统内各种功能和特权",
            articleCreatePoints, articleCommentPoints, articleLikePoints, dailyLoginPoints
        );
    }
}